package cn.huaqingcheng.tool.json.impl;

import cn.huaqingcheng.tool.json.JsonProvide;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.core.json.JsonWriteFeature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.Serial;
import java.util.List;

/**
 * JsonProvideJacksonImpl
 */
public class JsonProvideJacksonImpl implements JsonProvide {

    private static final ObjectMapper OM = JsonMapper.builder()
        .findAndAddModules()
        // 读取: 宽松风格, 接近 json5
        .enable(
            /* 允许 C 类型注释 */ JsonReadFeature.ALLOW_JAVA_COMMENTS,
            /* 允许不带引号的字段名 */ JsonReadFeature.ALLOW_UNQUOTED_FIELD_NAMES,
            /* 允许控制字符 */ JsonReadFeature.ALLOW_UNESCAPED_CONTROL_CHARS,
            /* 允许尾随逗号 */ JsonReadFeature.ALLOW_TRAILING_COMMA
        )
        // 写出
        .enable( /* 将数字写为字符串 */ JsonWriteFeature.WRITE_NUMBERS_AS_STRINGS)
        // 映射器
        .enable(
            /* 接受不区分大小写的属性 */ MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES,
                                         // MapperFeature.USE_STD_BEAN_NAMING,
            /* 接受不区分大小写的枚举名 */ MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS
        )
        .disable( /* 忽略未知属性 */ DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
        .disable( /* 找不到访问器不失败 */ SerializationFeature.FAIL_ON_EMPTY_BEANS)
        .build();

    private static final ObjectMapper OM_INDEX = OM.copy()
        .enable( /* 使用缩进输出 */ SerializationFeature.INDENT_OUTPUT);

    @Serial
    private static final long serialVersionUID = 1L;

    @Override
    public @NotNull String toFormatJson(@Nullable Object o) {
        try {
            return OM_INDEX.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public @NotNull String toJson(Object o) {
        try {
            return OM.writeValueAsString(o);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <T> T parse(@Nullable String json, @NotNull Class<T> tClass) {
        try {
            return OM.readValue(json, tClass);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public <E> List<E> parseList(@Nullable String json, @NotNull Class<E> type) {
        try {
            return OM.readValue(json, new TypeReference<>() {});
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

}
